#pragma once
#include "core/core.h"
#include <USB.h>
#include <USBHID.h>

#define TOUCH_LOCAL_NUM 0x1E   // 触控位点
#define REPORTID_TOUCHPAD 0xAA // TOUCH ID
#define KEYBOARD_ID 0x02       // 键盘ID (ID, ID+1)

#define USB_NAME "maimai_TouchPad"

//@huhuzhu
// 触控输入HID设备描述
/**
 * 2 keyboard + 1 touch screen
 * https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-sample-report-descriptors
 * https://www.usbzh.com/article/detail-562.html
 * https://www.likecs.com/show-308126193.html#sc=400
 * https://blog.csdn.net/yunwen3344/article/details/8107439
 * https://blog.csdn.net/fengli1995/article/details/120708460
 * https://learn.microsoft.com/zh-cn/windows-hardware/design/component-guidelines/sample-report-descriptor--parallel-hybrid-mode-
 * https://blog.csdn.net/qq_28738985/article/details/104026994 //多点报文
 * https://www.usbzh.com/tool/usb.html //HID分析工具
 *
 */

static const uint8_t init_packet[] = {
    0x05, 0x0D,
    0x09, 0x04, // USAGE (Touch)
    0xA1, 0x01,
    0x85, REPORTID_TOUCHPAD, //   REPORT_ID (Touch pad)
    0x09, 0x22,
    0xA1, 0x02,
    0x09, 0x42,
    0x15, 0x00, // REPORT
    0x25, 0x01, // REPORT MAX
    0x75, 0x01, // REPORT_SIZE
    0x95, 0x01,
    0x81, 0x02, // Interrupt
    0x09, 0x30,
    0x25, 0x7F,
    0x75, 0x07,
    0x95, 0x01,
    0x81, 0x02,
    0x09, 0x51,
    0x26, 0xFF, 0x00,
    0x75, 0x08,
    0x95, 0x01,
    0x81, 0x02,
    0x05, 0x01,
    0x09, 0x30,
    0x09, 0x31,
    0x26, 0xFF, 0x7F,
    0x65, 0x00,
    0x75, 0x10, // REPORT_SIZE
    0x95, 0x02,
    0x81, 0x02,
    0xC0,
    0x05, 0x0D,
    0x47, 0xff, 0xff, 0x00, 0x00, //  PHYSICAL_MAXIMUM X (65535)
    0x27, 0xff, 0xff, 0x00, 0x00, //  LOGICAL_MAXIMUM (65535)
    0x47, 0xff, 0xff, 0x00, 0x00, //  PHYSICAL_MAXIMUM Y (65535)
    0x75, 0x10,                   // REPORT_SIZE
    0x95, 0x01,
    0x09, 0x56,
    0x81, 0x02, // Interrupt
    0x09, 0x54,
    0x25, TOUCH_LOCAL_NUM,
    0x75, 0x08,
    0x95, 0x01, // POINT COUNT
    0x81, 0x02,
    0x05, 0x0D,
    0x09, 0x55,
    0x25, TOUCH_LOCAL_NUM,
    0x75, 0x08,
    0x95, 0x01,
    0xB1, 0x02,
    0xC0,
    /* 41 */

    0x05, 0x01,        // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,        // USAGE (Keyboard)
    0xa1, 0x01,        // COLLECTION (Application)
    0x85, KEYBOARD_ID, // Report ID (2)
    0x05, 0x07,        //     USAGE_PAGE (Keyboard/Keypad)
    0x19, 0xe0,        //     USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,        //     USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,        //     LOGICAL_MINIMUM (0)
    0x25, 0x01,        //     LOGICAL_MAXIMUM (1)
    0x95, 0x08,        //     REPORT_COUNT (8)
    0x75, 0x01,        //     REPORT_SIZE (1)
    0x81, 0x02,        //     INPUT (Data,Var,Abs)
    0x95, 0x01,        //     REPORT_COUNT (1)
    0x75, 0x08,        //     REPORT_SIZE (8)
    0x81, 0x03,        //     INPUT (Cnst,Var,Abs)
    0x95, 0x06,        //   REPORT_COUNT (6)
    0x75, 0x08,        //   REPORT_SIZE (8)
    0x15, 0x00,        //   LOGICAL_MINIMUM (0)
    0x25, 0xFF,        //   LOGICAL_MAXIMUM (255)
    0x05, 0x07,        //   USAGE_PAGE (Keyboard/Keypad)
    0x19, 0x00,        //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,        //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,        //     INPUT (Data,Ary,Abs)
    0x25, 0x01,        //     LOGICAL_MAXIMUM (1)
    0x95, 0x05,        //   REPORT_COUNT (5)
    0x75, 0x01,        //   REPORT_SIZE (1)
    0x05, 0x08,        //   USAGE_PAGE (LEDs)
    0x19, 0x01,        //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,        //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,        //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,        //   REPORT_COUNT (1)
    0x75, 0x03,        //   REPORT_SIZE (3)
    0x91, 0x03,        //   OUTPUT (Cnst,Var,Abs)
    0xc0,              //   END_COLLECTION

    0x05, 0x01,            // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,            // USAGE (Keyboard)
    0xa1, 0x01,            // COLLECTION (Application)
    0x85, KEYBOARD_ID + 1, // Report ID (2)
    0x05, 0x07,            //     USAGE_PAGE (Keyboard/Keypad)
    0x19, 0xe0,            //     USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,            //     USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,            //     LOGICAL_MINIMUM (0)
    0x25, 0x01,            //     LOGICAL_MAXIMUM (1)
    0x95, 0x08,            //     REPORT_COUNT (8)
    0x75, 0x01,            //     REPORT_SIZE (1)
    0x81, 0x02,            //     INPUT (Data,Var,Abs)
    0x95, 0x01,            //     REPORT_COUNT (1)
    0x75, 0x08,            //     REPORT_SIZE (8)
    0x81, 0x03,            //     INPUT (Cnst,Var,Abs)
    0x95, 0x06,            //   REPORT_COUNT (6)
    0x75, 0x08,            //   REPORT_SIZE (8)
    0x15, 0x00,            //   LOGICAL_MINIMUM (0)
    0x25, 0xFF,            //   LOGICAL_MAXIMUM (255)
    0x05, 0x07,            //   USAGE_PAGE (Keyboard/Keypad)
    0x19, 0x00,            //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,            //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,            //     INPUT (Data,Ary,Abs)
    0x25, 0x01,            //     LOGICAL_MAXIMUM (1)
    0x95, 0x05,            //   REPORT_COUNT (5)
    0x75, 0x01,            //   REPORT_SIZE (1)
    0x05, 0x08,            //   USAGE_PAGE (LEDs)
    0x19, 0x01,            //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,            //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,            //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,            //   REPORT_COUNT (1)
    0x75, 0x03,            //   REPORT_SIZE (3)
    0x91, 0x03,            //   OUTPUT (Cnst,Var,Abs)
    0xc0                   // END_COLLECTION
};

/*
static const uint8_t init_packet[] = {

    0x05,
    0x01, // USAGE_PAGE (Generic Desktop)
    0x09,
    0x06, // USAGE (Keyboard)
    0xa1,
    0x01, // COLLECTION (Application)
    0x85,
    0x01, // Report ID (1)
    0x05,
    0x07, //     USAGE_PAGE (Keyboard/Keypad)
    0x19,
    0xe0, //     USAGE_MINIMUM (Keyboard LeftControl)
    0x29,
    0xe7, //     USAGE_MAXIMUM (Keyboard Right GUI)
    0x15,
    0x00, //     LOGICAL_MINIMUM (0)
    0x25,
    0x01, //     LOGICAL_MAXIMUM (1)
    0x95,
    0x08, //     REPORT_COUNT (8)
    0x75,
    0x01, //     REPORT_SIZE (1)
    0x81,
    0x02, //     INPUT (Data,Var,Abs)
    0x95,
    0x01, //     REPORT_COUNT (1)
    0x75,
    0x08, //     REPORT_SIZE (8)
    0x81,
    0x03, //     INPUT (Cnst,Var,Abs)
    0x95,
    0x06, //   REPORT_COUNT (6)
    0x75,
    0x08, //   REPORT_SIZE (8)
    0x15,
    0x00, //   LOGICAL_MINIMUM (0)
    0x25,
    0xFF, //   LOGICAL_MAXIMUM (255)
    0x05,
    0x07, //   USAGE_PAGE (Keyboard/Keypad)
    0x19,
    0x00, //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29,
    0x65, //   USAGE_MAXIMUM (Keyboard Application)
    0x81,
    0x00, //     INPUT (Data,Ary,Abs)
    0x25,
    0x01, //     LOGICAL_MAXIMUM (1)
    0x95,
    0x05, //   REPORT_COUNT (5)
    0x75,
    0x01, //   REPORT_SIZE (1)
    0x05,
    0x08, //   USAGE_PAGE (LEDs)
    0x19,
    0x01, //   USAGE_MINIMUM (Num Lock)
    0x29,
    0x05, //   USAGE_MAXIMUM (Kana)
    0x91,
    0x02, //   OUTPUT (Data,Var,Abs)
    0x95,
    0x01, //   REPORT_COUNT (1)
    0x75,
    0x03, //   REPORT_SIZE (3)
    0x91,
    0x03, //   OUTPUT (Cnst,Var,Abs)
    0xc0, // END_COLLECTION

    0x05,
    0x01, // USAGE_PAGE (Generic Desktop)
    0x09,
    0x06, // USAGE (Keyboard)
    0xa1,
    0x01, // COLLECTION (Application)
    0x85,
    0x02, // Report ID (2)
    0x05,
    0x07, //     USAGE_PAGE (Keyboard/Keypad)
    0x19,
    0xe0, //     USAGE_MINIMUM (Keyboard LeftControl)
    0x29,
    0xe7, //     USAGE_MAXIMUM (Keyboard Right GUI)
    0x15,
    0x00, //     LOGICAL_MINIMUM (0)
    0x25,
    0x01, //     LOGICAL_MAXIMUM (1)
    0x95,
    0x08, //     REPORT_COUNT (8)
    0x75,
    0x01, //     REPORT_SIZE (1)
    0x81,
    0x02, //     INPUT (Data,Var,Abs)
    0x95,
    0x01, //     REPORT_COUNT (1)
    0x75,
    0x08, //     REPORT_SIZE (8)
    0x81,
    0x03, //     INPUT (Cnst,Var,Abs)
    0x95,
    0x06, //   REPORT_COUNT (6)
    0x75,
    0x08, //   REPORT_SIZE (8)
    0x15,
    0x00, //   LOGICAL_MINIMUM (0)
    0x25,
    0xFF, //   LOGICAL_MAXIMUM (255)
    0x05,
    0x07, //   USAGE_PAGE (Keyboard/Keypad)
    0x19,
    0x00, //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29,
    0x65, //   USAGE_MAXIMUM (Keyboard Application)
    0x81,
    0x00, //     INPUT (Data,Ary,Abs)
    0x25,
    0x01, //     LOGICAL_MAXIMUM (1)
    0x95,
    0x05, //   REPORT_COUNT (5)
    0x75,
    0x01, //   REPORT_SIZE (1)
    0x05,
    0x08, //   USAGE_PAGE (LEDs)
    0x19,
    0x01, //   USAGE_MINIMUM (Num Lock)
    0x29,
    0x05, //   USAGE_MAXIMUM (Kana)
    0x91,
    0x02, //   OUTPUT (Data,Var,Abs)
    0x95,
    0x01, //   REPORT_COUNT (1)
    0x75,
    0x03, //   REPORT_SIZE (3)
    0x91,
    0x03, //   OUTPUT (Cnst,Var,Abs)
    0xc0, // END_COLLECTION

    0x05, 0x0D,
    0x09, 0x04,
    0xA1, 0x01,
    0x09, 0x22,
    0xA1, 0x02,
    0x09, 0x42,
    0x15, 0x00,
    0x25, 0x01,
    0x75, 0x01,
    0x95, 0x01,
    0x81, 0x02,
    0x09, 0x30,
    0x25, 0x7F,
    0x75, 0x07,
    0x95, 0x01,
    0x81, 0x02,
    0x09, 0x51,
    0x26, 0xFF, 0x00,
    0x75, 0x08,
    0x95, 0x01,
    0x81, 0x02,
    0x05, 0x01,
    0x09, 0x30,
    0x09, 0x31,
    0x26, 0xFF, 0x7F,
    0x65, 0x00,
    0x75, 0x10,
    0x95, 0x02,
    0x81, 0x02,
    0xC0,

    0x05, 0x0D,
    0x27, 0xFF, 0xFF, 0x00, 0x00,
    0x75, 0x10,
    0x95, 0x01,
    0x09, 0x56,
    0x81, 0x02,
    0x09, 0x54,
    0x25, REPORTID_TOUCHPAD,
    0x75, 0x08,
    0x95, 0x01,
    0x81, 0x02,
    0x05, 0x0D,
    0x09, 0x55,
    0x75, 0x08,
    0x95, 0x01,
    0xB1, 0x02,
    0xC0
};
static const uint8_t init_packet[] = {
    0x05, 0x0D,
    0x09, 0x04,
    0xA1, 0x01,
    0x09, 0x22,
    0xA1, 0x02,
    0x09, 0x42,
    0x15, 0x00,
    0x25, 0x01,
    0x75, 0x01,
    0x95, 0x01,
    0x81, 0x02,
    0x09, 0x30,
    0x25, 0x7F,
    0x75, 0x07,
    0x95, 0x01,
    0x81, 0x02,
    0x09, 0x51,
    0x26, 0xFF, 0x00,
    0x75, 0x08,
    0x95, 0x01,
    0x81, 0x02,
    0x05, 0x01,
    0x09, 0x30,
    0x09, 0x31,
    0x26, 0xFF, 0x7F,
    0x65, 0x00,
    0x75, 0x10,
    0x95, 0x02,
    0x81, 0x02,
    0xC0,
    0x05, 0x0D,
    0x27, 0xFF, 0xFF, 0x00, 0x00,
    0x75, 0x10,
    0x95, 0x01,
    0x09, 0x56,
    0x81, 0x02,
    0x09, 0x54,
    0x25, 0x0A,
    0x75, 0x08,
    0x95, 0x01,
    0x81, 0x02,
    0x05, 0x0D,
    0x09, 0x55,
    0x25, 0x0A,
    0x75, 0x08,
    0x95, 0x01,
    0xB1, 0x02,
    0xC0};
*/

static const char const_touchpoint[35][3] = {
    "No",
    "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8",
    "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8",
    "C1", "C2",
    "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8",
    "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8"};


class USB_OTG
{
public:
    static void init();
    static void serial_begin();

    // Multi TOUCH
    //  X: 0-32768 Y:0-32768 STATE: 0-255 ID: 0-19 COUNT: 1-20
    static IRAM_ATTR void Send_touchscreen(uint8_t On /*是否按下*/, uint16_t X_axis /*X坐标*/, uint16_t Y_axis /*Y坐标*/, uint8_t Id /*点位ID*/, uint8_t Multi = 0 /*同时存在位点*/, millis_t timer = 0 /*同步时间*/);
    static IRAM_ATTR void Send_keyboard(uint8_t *pull_down);
    static IRAM_ATTR void Send_maiserial(uint32_t send1/*1-5*/, uint32_t send2/*6-7*/ /*最右侧一位无效*/);
    static IRAM_ATTR void serial_recv();
    static bool HID_ready();
    static void HID_end();
    static void Touch_idle();

    static uint8_t HID_state;
    
private:
    static volatile uint8_t touch_data[64];
};

extern USB_OTG usb;